import { BoneCreaterController } from "./BoneCreaterController";
import { ArmatureController } from "../ArmatureController";
import { IMode, IOperator } from "./IMode";
import { TransformController } from "./TransformController";
import { ScaleController } from "./ScaleController";
import { TranslateController } from "./TranslateController";
import { RotateController } from "./RotateController";

export const enum ModeType {
    BoneCreater = "boneCreater",
    Transform = "transform",
    Translate = "translate",
    Rotate = "rotate",
    Scale = "scale",
}

export interface StringKeyMap<T> {
    [key: string]: T;
}

export class ModeController implements IOperator {
    private _ctrl: ArmatureController;
    private _modeList: StringKeyMap<IMode> = {};
    private _isDraging = false;
    public curMode = ModeType.Transform;

    constructor(ctrl: ArmatureController) {
        this._ctrl = ctrl;
        this._modeList[ModeType.BoneCreater] = new BoneCreaterController(this._ctrl);
        this._modeList[ModeType.Transform] = new TransformController(this._ctrl);
        this._modeList[ModeType.Scale] = new ScaleController(this._ctrl);
        this._modeList[ModeType.Translate] = new TranslateController(this._ctrl);
        this._modeList[ModeType.Rotate] = new RotateController(this._ctrl);
        this.registerEvent();
    }

    public registerEvent(): void {
        this._ctrl.view.parent.on("pointerdown", this.onDragStart, this);
        this._ctrl.view.parent.on('pointerup', this.onDragMoveEnd, this);
        this._ctrl.view.parent.on('pointerupoutside', this.onDragMoveEnd, this);
        this._ctrl.view.parent.on("pointermove", this.onPointerMove, this);

    }

    public unRegisterEvent(): void {
        this._ctrl.view.parent.off("pointerdown", this.onDragStart, this);
        this._ctrl.view.parent.off('pointerup', this.onDragMoveEnd, this);
        this._ctrl.view.parent.off('pointerupoutside', this.onDragMoveEnd, this);
        this._ctrl.view.parent.off("pointermove", this.onPointerMove, this);
    }

    public onPointerMove(event: any): void {
        if (this._isDraging) {
            this.onDragMove(event);
        } else {
            this.onHover(event);
        }
    }

    public onDragStart(event: any): void {
        this._isDraging = true;
        this._modeList[this.curMode].onDragStart(event);
    }

    public onDragMove(event: any): void {
        this._modeList[this.curMode].onDragMove(event);
    }
    public onDragMoveEnd(event: any): void {
        this._modeList[this.curMode].onDragMoveEnd(event);
        this._isDraging = false;
    }

    public onHover(event: any): void {
        this._modeList[this.curMode].onHover(event);
    }

    public switchMode(modeType: ModeType): void {
        if (modeType === this.curMode) {
            return;
        }

        if (this.curMode) {
            this._modeList[this.curMode].onLeave();
        }

        this.curMode = modeType;
        this._modeList[this.curMode].onEnter();
    }

    public updateOperateBar(visible: boolean): void {
        this._modeList[this.curMode].updateOperateBar(visible);
    }
}